using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;

namespace PrinterHack
{
    public partial class frmMain : Form
    {
        #region Variables
        protected const int PJL_PORT = 9100;
        protected static string message = "NO MESSAGE";
        protected bool showForm = true;
        protected IPEndPoint ipEndPoint;
        protected Socket socket;
        #endregion

        #region Public Propteries
        public static string DataFile = Application.StartupPath + "\\Printers.xml";  //Used to store added printers
        public static string SchemaFile = Application.StartupPath + "\\PrinterSchema.xsd";
        #endregion

        #region Constructor
        public frmMain()
        {
            InitializeComponent();
        }
        #endregion

        #region Custom Methods

        #region Private Methods
        private void ConnectToPrinter(string IPAddress, int Port)
        {
            //Loads the printer's IP address and port
            ipEndPoint = new IPEndPoint(Dns.GetHostEntry(IPAddress).AddressList[0], Port);

            //Creates a new socket to connect to the printer. (Streams data through TCP)
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            socket.Connect(ipEndPoint);            
        }

        private void CloseConnection()
        {
            socket.Close();
        }

        private int SendMessage(string Message)
        {
            //Convert to string message to a byte array.
            byte[] sendData;
            sendData = Encoding.ASCII.GetBytes(Message);

            //Send the message to the printer and return the result code.
            int result = 0;
            result = socket.Send(sendData, sendData.Length, 0);
            return result;
        }

        private string GetMessage(string Message)
        {
            //Sends the request to the printer.
            byte[] sendData;
            sendData = Encoding.ASCII.GetBytes(Message);
            int result = 0;
            result = socket.Send(sendData, sendData.Length, 0);

            //Gets the response back.
            byte[] receiveData = new Byte[64];
            string receiveString;
            result = socket.Receive(receiveData);
            receiveString = Encoding.ASCII.GetString(receiveData);
            return receiveString;
        }

        private void HideForm()
        {
            this.WindowState = FormWindowState.Minimized;
            this.ShowInTaskbar = false;
            showForm = false;
        }
        #endregion

        #region Public Methods
        public void RefreshData()
        {
            cboIP.DataSource = Printer.PrinterData.Tables["printer"];
            cboIP.DisplayMember = "name";
            cboIP.ValueMember = "id";
        }
        #endregion

        #endregion

        #region Event Handlers

        #region Form Events
        private void frmMain_Load(object sender, EventArgs e)
        {
            //If the file doesn't exist, create the Printers.xml file
            if (!File.Exists(frmMain.DataFile))
            {
                FileStream stream = File.Create(frmMain.DataFile);
                StreamWriter writer = new StreamWriter(stream);
                writer.WriteLine("<?xml version=\"1.0\" standalone=\"yes\"?>");
                writer.WriteLine("<printers>");
                writer.WriteLine("    <printer>");
                writer.WriteLine("        <id>" + Guid.NewGuid().ToString() + "</id>");
                writer.WriteLine("        <name>Test Printer</name>");
                writer.WriteLine("        <ip>192.168.1.1</ip>");
                writer.WriteLine("        <description>This is a test printer that is installed by default. Change the name and IP to your current HP Laserjet printer.</description>");
                writer.WriteLine("    </printer>");
                writer.WriteLine("</printers>");
                writer.Dispose();
                stream.Dispose();              
            }

            //Bind the printer list dropdown to the printers in the dataset
            cboIP.DataSource = Printer.PrinterData.Tables["printer"];
            cboIP.DisplayMember = "name";
            cboIP.ValueMember = "id";

            //Add each printer to the dropdown in the context menu in the taskbar
            foreach (DataRow row in Printer.PrinterData.Tables["printer"].Rows)
            {
                contextCboPrinter.Items.Add(row["name"]);
            }            
        }

        private void frmMain_FormClosed(object sender, FormClosedEventArgs e)
        {
            notifyIconMain.Dispose();
            Application.ExitThread();
        }

        private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            //e.Cancel = true;
            //this.Hide();
        }

        private void frmMain_Resize(object sender, EventArgs e)
        {            
            if (this.WindowState == FormWindowState.Minimized)
            {
                HideForm();
            }
            else
            {
                this.WindowState = FormWindowState.Normal;
                this.ShowInTaskbar = true;
                showForm = true;
            }
        }

        private void frmMain_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
            {
                //If the Esc key is entered, hide frmMain
                HideForm();
            }
        }
        #endregion

        #region Button Events
        private void btnSend_Click(object sender, EventArgs e)
        {
            try
            {
                string message = txtMessage.Text;
                string sendString = "";

                if (cboIP.SelectedValue.ToString() != "")
                {
                    Printer printer = new Printer(cboIP.SelectedValue.ToString());

                    if (cboAction.Text == "Send Message")
                    {
                        if (txtMessage.Text == "")
                        {
                            MessageBox.Show("Please enter a valid message to send.");
                            return;
                        }
                        else
                        {
                            ConnectToPrinter(printer.IP, PJL_PORT);
                            sendString = String.Format("\x1B%-12345X@PJL RDYMSG DISPLAY = \"{0}\"\r\n\x1B%-12345X\r\n", message);
                            if (SendMessage(sendString) == 0)
                            {
                                MessageBox.Show("Could not send on socket");
                            }
                            else
                            {
                                MessageBox.Show("Message Sent!");
                            }

                            CloseConnection();
                        }
                    }
                    else
                    {
                        ConnectToPrinter(printer.IP, PJL_PORT);
                        sendString = String.Format("\x1B%-12345X@PJL INFO STATUS\r\n\x1B%-12345X\r\n", message);
                        MessageBox.Show("== PRINTER MESSAGE ==\n\n" + GetMessage(sendString));
                        CloseConnection();
                    }
                }
                else
                {
                    MessageBox.Show("Please enter a valid IP of the printer to read.");
                    return;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            frmAdd add = new frmAdd(this);
            add.ShowDialog();
        }
        #endregion

        #region Top Menu Events
        private void mnuFileExit_Click(object sender, EventArgs e)
        {
            Application.Exit();
            this.Dispose();
        }

        private void mnuHide_Click(object sender, EventArgs e)
        {
            HideForm();
        }

        private void mnuEditPrinters_Click(object sender, EventArgs e)
        {
            frmPrinters printers = new frmPrinters(this);
            printers.ShowDialog();
        }

        private void mnuHelpDonate_Click(object sender, EventArgs e)
        {
            string targetURL = "http://www.tekdev.com/donate.aspx";
            System.Diagnostics.Process.Start(targetURL);
        }
        #endregion

        #region Context Menu Events
        private void contextExit_Click(object sender, EventArgs e)
        {
            notifyIconMain.Visible = false;
            notifyIconMain.Dispose();
            Application.Exit();
            this.Dispose();
            Application.ExitThread();
        }

        private void contextShowHide_Click(object sender, EventArgs e)
        {
            if (this.showForm == true)
            {
                HideForm();
            }
            else
            {
                this.ShowInTaskbar = true;
                this.WindowState = FormWindowState.Normal;
                showForm = true;
            }
        }

        private void contextCboPrinter_SelectedIndexChanged(object sender, EventArgs e)
        {
            contextMenuMain.Hide();
            Printer printer = new Printer();
            printer.LoadDataByName(contextCboPrinter.Text);
            string sendString = "";
            ConnectToPrinter(printer.IP, PJL_PORT);
            sendString = String.Format("\x1B%-12345X@PJL INFO STATUS\r\n\x1B%-12345X\r\n", message);
            MessageBox.Show("== PRINTER MESSAGE ==\n\n" + GetMessage(sendString));
            CloseConnection();
        }
        #endregion

        #region NotifyIcon Events
        private void notifyIconMain_DoubleClick(object sender, EventArgs e)
        {
            this.ShowInTaskbar = true;
            this.Show();
            this.WindowState = FormWindowState.Normal;
        }

        private void notifyIconMain_Click(object sender, EventArgs e)
        {

        }

        private void notifyIconMain_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                //MessageBox.Show();
                contextMenuMain.Show();
            }
        }
        #endregion

        #region Text Events
        private void cboAction_KeyPress(object sender, KeyPressEventArgs e)
        {
            e.Handled = true;
        }

        private void cboIP_KeyPress(object sender, KeyPressEventArgs e)
        {
            e.Handled = true;
        }

        private void cboAction_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
            {
                HideForm();
            }
        }

        private void cboIP_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
            {
                HideForm();
            }
        }

        private void txtMessage_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
            {
                HideForm();
            }
        }
        #endregion

        #endregion





    }
}